package com.code2roc.jarmanage.util;

import com.code2roc.jarmanage.depoly.DepolyPlatform;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

public class ZipUtil {

    public static Boolean compress(String inputFileName, String zipFileName, String zipGuid) throws Exception {
        compress(zipFileName, new File(inputFileName), zipGuid);
        return true;
    }

    private static void compress(String zipFileName, File inputFile, String zipGuid) throws Exception {
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
        try {
            if (inputFile.isDirectory()) {
                long totalSize = FileUtil.getTotalSize(inputFile);
                compress(out, inputFile, inputFile.getName(), zipGuid, totalSize);
            } else {
                compressFile(out, inputFile);
            }
        } catch (Exception e) {
            LogUtil.error(e);
            throw e;
        } finally {
            out.flush();
            out.close();
        }
    }

    private static void compress(ZipOutputStream out, File f, String base, String zipGuid, long totalSize) throws Exception {
        if (f.isDirectory()) {
            File[] fl = f.listFiles();
            out.putNextEntry(new ZipEntry(base + "/"));
            base = base.length() == 0 ? "" : base + "/";
            for (int i = 0; i < fl.length; i++) {
                compress(out, fl[i], base + fl[i].getName(), zipGuid, totalSize);
            }
        } else {
            WritableByteChannel writableByteChannel = null;
            ByteBuffer buffer = ByteBuffer.allocate(2048);
            writableByteChannel = Channels.newChannel(out);
            out.putNextEntry(new ZipEntry(base));
            FileChannel fileChannel = new FileInputStream(f).getChannel();
            while (fileChannel.read(buffer) != -1) {
                //更新缓存区位置
                buffer.flip();
                while (buffer.hasRemaining()) {
                    writableByteChannel.write(buffer);
                }
                buffer.rewind();
            }
            fileChannel.close();
            File file = new File("templatefiles");
            if (!file.exists()) {
                file.mkdirs();
            }
            String fileName = "templatefiles/" + zipGuid;
            file = new File(fileName);
            if (!file.exists()) {
                FileUtil.writeFile(fileName, FileUtil.getTotalSize(f) + "|" + FileUtil.getTotalSize(f) * 100 / totalSize, false);
            } else {
                String content = FileUtil.readFileContent(fileName);
                long zipTotal = Long.parseLong(content.split("\\|")[0]) + FileUtil.getTotalSize(f);
                FileUtil.writeFile(fileName, zipTotal + "|" + zipTotal * 100 / totalSize, false);
            }
        }
    }

    private static void compressFile(ZipOutputStream out, File f) throws Exception {
        WritableByteChannel writableByteChannel = null;
        ByteBuffer buffer = ByteBuffer.allocate(2048);
        writableByteChannel = Channels.newChannel(out);
        out.putNextEntry(new ZipEntry(f.getName()));
        FileChannel fileChannel = new FileInputStream(f).getChannel();
        while (fileChannel.read(buffer) != -1) {
            //更新缓存区位置
            buffer.flip();
            while (buffer.hasRemaining()) {
                writableByteChannel.write(buffer);
            }
            buffer.rewind();
        }
        fileChannel.close();
    }

    public static void decompress(String srcPath, String dest) throws IOException {
        File file = new File(srcPath);
        ZipFile zf = null;
        if (EnviromentUtil.getDepolyPlaform() == DepolyPlatform.Windows) {
            zf = new ZipFile(file, Charset.forName("GBK"));
        } else {
            zf = new ZipFile(file, Charset.forName("UTF-8"));
        }
        try {
            Enumeration entries = zf.entries();
            ZipEntry entry = null;
            while (entries.hasMoreElements()) {
                entry = (ZipEntry) entries.nextElement();
                if (entry.isDirectory() || StringUtil.isEmpty(entry.getName())) {
                    String dirPath = dest + File.separator + entry.getName();
                    File dir = new File(dirPath);
                    dir.mkdirs();
                } else {
                    // 表示文件
                    File f = new File(dest + File.separator + entry.getName());
                    if (!f.exists()) {
                        //String dirs = FileUtils.getParentPath(f);
                        String dirs = f.getParent();
                        File parentDir = new File(dirs);
                        parentDir.mkdirs();
                    }
                    f.createNewFile();
                    // 将压缩文件内容写入到这个文件中
                    InputStream is = zf.getInputStream(entry);
                    FileOutputStream fos = new FileOutputStream(f);
                    int count;
                    byte[] buf = new byte[8192];
                    while ((count = is.read(buf)) != -1) {
                        fos.write(buf, 0, count);
                    }
                    is.close();
                    fos.close();
                }
            }
        } catch (Exception e) {
            LogUtil.error(e);
            throw e;
        } finally {
            zf.close();
        }
    }
}
